package top.yudoge.dogeeditor.db.datasource

import com.zaxxer.hikari.HikariDataSource
import top.yudoge.dogeeditor.db.objects.DataSourceConfig
import javax.sql.DataSource

/**
 * @author Yudoge
 * @since 2025/03/19
 *
 * The DataSourceManager implementation with HikariCP
 *
 * ExtraParams:
 * - connectionTimeout: Long   default to 30000
 * - maxLifeTime: Long         default to 1800000
 * - minimumIdle: Long         default to 1
 * - maximumPoolSize: Long     default to 5
 */
class HikariCPDataSourceManager : DataSourceManager {

    private val dataSources = mutableMapOf<String, DataSource>()
    private val dataSourceConfigMap = mutableMapOf<String, DataSourceConfig>()

    override fun register(configs: List<DataSourceConfig>) {
        for (config in configs) {
            val dataSource = buildDataSource(config)
            dataSources[config.identifier] = dataSource
            dataSourceConfigMap[config.identifier] = config
        }
    }

    override fun getDataSource(identifier: String): DataSource? {
        return dataSources[identifier]
    }

    override fun listDataSourceIdentifiers(): List<String> {
        return dataSources.keys.toList()
    }

    override fun listDataSourceConfig(): List<DataSourceConfig> {
        return dataSourceConfigMap.values.toList()
    }


    private fun buildDataSource(config: DataSourceConfig): HikariDataSource {
        val dataSource = HikariDataSource()
        dataSource.jdbcUrl = config.url
        dataSource.username = config.username
        dataSource.password = config.password
        if (config.extraParams != null) {
            config.extraParams[CONNETION_TIME_OUT]?.let {
                dataSource.connectionTimeout = it as Long
            }
            config.extraParams[MAX_LIFE_TIME]?.let {
                dataSource.maxLifetime = it as Long
            }
            config.extraParams[MINIMUM_IDLE]?.let {
                dataSource.minimumIdle = it as Int
            }
            config.extraParams[MAXIMUM_POOL_SIZE]?.let {
                dataSource.maximumPoolSize = it as Int
            }
        }
        return dataSource
    }

    companion object {
        val CONNETION_TIME_OUT = "connectionTimeout";
        val MAX_LIFE_TIME = "maxLifeTime";
        val MINIMUM_IDLE = "minimumIdle";
        val MAXIMUM_POOL_SIZE = "maximumPoolSize";
    }
}